package com.flute.framework.util.ftp;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;

import org.apache.commons.io.IOUtils;

import com.flute.framework.search.ProviderInfo;
import com.flute.tools.util.FileUtil;

public class LocalFile implements IFileOperation {
	public static final String DEFAULT_PROTOCOL = "file";

	@Override
	public boolean createNewFile(String uri) throws Exception {
		return new File(uri).createNewFile();
	}

	@Override
	public boolean delete(String uri) throws Exception {
		return new File(uri).delete();
	}

	public boolean copyFile(String source, String targe) {
		return copyFileByIs(source, targe);
	}

	public boolean copyFileByIs(String source, String targe) {
		InputStream bis = null;
		OutputStream bos = null;
		try {
			bis = new FileInputStream(source);
			bos = new FileOutputStream(targe);
			byte[] buff = new byte[1024];
			int len = 0;
			while ((len = bis.read(buff)) != -1) {
				bos.write(buff, 0, len);
			}
			return new File(source).length() == new File(targe).length();
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} finally {
			IOUtils.closeQuietly(bis);
			IOUtils.closeQuietly(bos);
		}
	}

	public boolean copyFileByChannel(String source, String targe) {
		long destSize = 0, srcSize = 0;
		try {
			// Create channel on the source
			FileChannel srcChannel = new FileInputStream(source).getChannel();

			// Create channel on the destination
			FileChannel dstChannel = new FileOutputStream(targe).getChannel();
			srcSize = srcChannel.size();
			long pos = 0;
			int retry = 0;
			while (retry++ < 5 && pos < srcSize) {
				if (retry > 1) {
					System.err.println("retry " + retry + " at pos ");
				}

				// Copy file contents from source to destination
				// pos += dstChannel.transferFrom(srcChannel, pos, srcSize-pos);
				pos += srcChannel.transferTo(pos, srcSize - pos, dstChannel);

			}
			destSize = pos;

			// Close the channels
			srcChannel.close();
			dstChannel.close();

			if (srcSize != destSize) {
				System.err.println("copy file from " + source + " to " + targe
						+ " Size error: " + srcSize + " - " + destSize);
				return false;
			}

		} catch (IOException e) {
			e.printStackTrace();
			// System.out.println("copy file from " + source + " to " + targe
			// + " Fail!", LilyMonitor.getSearcherKey());
			return false;
		}
		return true;
	}

	@Override
	public boolean exists(String uri) throws Exception {
		return new File(uri).exists();
	}

	@Override
	public void init() throws Exception {
		// do something
	}

	@Override
	public boolean isDirectory(String uri) throws Exception {
		return new File(uri).isDirectory();
	}

	@Override
	public boolean isFile(String uri) throws Exception {
		return new File(uri).isFile();
	}

	@Override
	public String[] list(String uri) throws Exception {
		return new File(uri).list();
	}

	@Override
	public InputStream load(String uri) throws Exception {
		return new FileInputStream(uri);
	}

	@Override
	public boolean mkdir(String uri) throws Exception {
		File dir = new File(uri);
		return dir.isDirectory() || dir.mkdir();
	}

	@Override
	public boolean mkdirs(String uri) throws Exception {
		File dir = new File(uri);
		return dir.isDirectory() || dir.mkdirs();
	}

	@Override
	public boolean save(String uri, InputStream is) throws Exception {
		FileOutputStream fos = null;
		BufferedInputStream stream = null;
		try {
			fos = new FileOutputStream(uri);
			stream = new BufferedInputStream(is);
			byte[] buf = new byte[1024];
			int bytesRead = stream.read(buf);
			while (bytesRead >= 0) {
				fos.write(buf, 0, bytesRead);
				bytesRead = stream.read(buf);
			}
		} finally {
			fos.close();
		}
		return new File(uri).exists();
	}

	@Override
	public boolean upload(String filename, String uri) throws Exception {
		return download(filename, uri);
	}

	@Override
	public void finalise() {
		// do something
	}

	@Override
	public boolean delete(String uri, String fileName) throws Exception {
		return new File(uri, fileName).delete();
	}

	@Override
	public boolean createNewFile(String uri, String name) throws Exception {
		return new File(uri, name).createNewFile();
	}

	@Override
	public boolean removeDirectory(String uri) throws Exception {
		return delete(uri);
	}

	public static IFileOperation parse(ProviderInfo info) throws Exception {
		IFileOperation oper = new LocalFile();
		oper.init();
		return oper;
	}

	@Override
	public boolean download(String uri, String filename) throws Exception {
		File source = new File(uri);
		File targe = new File(filename);
		boolean result = true;
		if (targe.isDirectory() && source.isFile()) {
			targe = new File(targe.getAbsolutePath()
					+ System.getProperty("file.separator") + source.getName());
		}
		if (source.exists()) {
			if (source.isFile()) {
				result = copyFile(uri, targe.getAbsolutePath());
			} else {
				if (!targe.exists()) {
					result = targe.mkdirs();
				}
				if (result) {
					if (targe.isDirectory()) {
						for (File f : source.listFiles()) {
							result &= download(f.getAbsolutePath(), targe
									.getAbsolutePath()
									+ System.getProperty("file.separator")
									+ f.getName());
						}
					} else {
						result = false;
					}
				}
			}
		}
		return result;
	}

	@Override
	public long getNotLockLastModifiedTime(String folder) {
		File f = new File(folder);
		File[] fileArray = f.listFiles();
		long lastmodified = -1;
		if (fileArray != null) {
			for (int i = 0; i < fileArray.length; i++) {
				if (!fileArray[i].getName().endsWith(".lock")
						&& lastmodified < fileArray[i].lastModified()) {
					lastmodified = fileArray[i].lastModified();
				}
			}
		}
		return lastmodified;
	}

	@Override
	public long lastModified(String uri) throws IOException {
		return new File(uri).lastModified();
	}

	@Override
	public long size(String uri) throws Exception {
		return new File(uri).length();
	}

	@Override
	public String getSeparator() {
		return System.getProperty("file.separator");
	}

	@Override
	public String combin(String uri, String fileName) {
		if (uri == null || uri.trim().length() <= 0)
			throw new IllegalArgumentException("uri=" + uri);
		if (fileName == null || fileName.trim().length() <= 0)
			throw new IllegalArgumentException("fileName=" + fileName);
		StringBuilder result = new StringBuilder(uri);
		result.append(uri.endsWith(getSeparator())
				|| uri.endsWith(COMMON_SEPARATOR) ? "" : getSeparator());
		int nativeSepapos = fileName.lastIndexOf(getSeparator());
		int commonSepaPos = fileName.lastIndexOf(COMMON_SEPARATOR);
		String singleName = fileName.substring(Math.max(nativeSepapos,
				commonSepaPos) + 1);
		result.append(singleName);
		return result.toString();
	}

	@Override
	public boolean clearFolder(String path, String name) {
		return FileUtil.clearFolder(path, name);
	}

	public static void main(String[] args) throws Exception {
		LocalFile file = new LocalFile();
		System.out.println(file.copyFile(
				"/home/xww/test/dwindex/searcher/basesong2/_0.cfx",
				"/home/xww/test/dwindex/searcher/_0.cfx"));
		// System.out.println(file.download("/home/xww/test/1/a",
		// "/home/xww/test/1/b"));
		// System.out.println(file.mkdir("/home/xww/test/1/2"));
		// System.out.println(file.combin("d:/1/2/3/d", "\\2"));

	}
}
